/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.elcom.emocbc.vlivetest20140310;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author GiangLT
 */
public class CbmCalculator {

    static String HEX_STRING = "0123456789ABCDEF";
    public static final int SIZE_1_PART = 88;
    private static final Logger LOG = LoggerFactory.getLogger(CbmCalculator.class);

    public static String convertBinary2Hexadecimal(byte[] binary) {
        StringBuilder buf = new StringBuilder();
        int block;

        for (int i = 0; i < binary.length; i++) {
            block = binary[i] & 0xFF;
            buf.append(HEX_STRING.charAt(block >> 4));
            buf.append(HEX_STRING.charAt(binary[i] & 0x0F));
            if (i < binary.length - 1) {
                buf.append(',');
            }
        }

        return buf.toString();
    }

    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }

    public static String stringToHex(String str) {
        char[] chars = str.toCharArray();
        StringBuilder strBuffer = new StringBuilder();
        for (int i = 0; i < chars.length; i++) {
            strBuffer.append(IntegerToHex((int) chars[i]));
        }
        return strBuffer.toString();
    }

    private static String IntegerToHex(int i) {
        if (i < 16) {
            return "0" + Integer.toHexString(i);
        }

        return Integer.toHexString(i);
    }

    private static String getMostContent(String addresses[]) {
        int howMany;
        int mostTimes = 1;
        String mostCommon = null;
        for (String addresse : addresses) {
            if (addresse == null || addresse.length() == 0) {
                continue;
            }
            howMany = 0;
            for (String addresse1 : addresses) {
                if (addresse.equals(addresse1)) {
                    howMany++;
                }
            }
            if (howMany > mostTimes) {
                mostTimes = howMany;
                mostCommon = addresse;
            }
        }

        return mostCommon;
    }

    private static int getMostNumber(int addresses[]) {
        int howMany;
        int mostTimes = 1;
        int mostCommon = 0;
        for (int i = 0; i < addresses.length; i++) {
            if (addresses[i] == 0) {
                continue;
            }
            howMany = 0;
            for (int j = 0; j < addresses.length; j++) {
                if (addresses[i] == (addresses[j])) {
                    howMany++;
                }
            }

            if (howMany > mostTimes) {
                mostTimes = howMany;
                mostCommon = addresses[i];
            }
        }

        return mostCommon;
    }

    private static String toShortCodeString(int defaultCode) {
        StringBuilder shortCode = new StringBuilder(String.valueOf(defaultCode));
        if (shortCode.length() % 2 == 1) {
            shortCode.append("F");
        }

        StringBuilder result = new StringBuilder();
        for (int i = 0; i < shortCode.length(); i += 2) {
            result.append(shortCode.charAt(i + 1)).append(shortCode.charAt(i));
        }

        return result.toString();
    }

    public static List<String> generateCBMStructFile(MenuItemDTO[] menu, String detail, int messageID, int topicID, int ind, String zone, String startTime, int broadcastId)
            throws IOException {
        int serialNumber = 0xB3A0;
        byte[] sum;
        int n = 0;
        int realSize = 0;
        int sizeM = 0;
        int sizeD;
        int lengthHide;
        String beginHex = "";
        String menuHex = "";
        String detailHex = "";

        int numberMenu = menu.length;

        int[] number = new int[menu.length];
        for (int i = 0; i < number.length; i++) {
            number[i] = menu[i].getShortcode();
        }

        String[] content = new String[menu.length];
        for (int i = 0; i < content.length; i++) {
            content[i] = menu[i].getContent();
            LOG.debug("content" + i + ": " + content[i]);
        }

        int defaultNumber = getMostNumber(number);
        String defaultContent = getMostContent(content);

        //for Test
//		defaultNumber = 0;
//		defaultContent = null;
        LOG.debug("Start broadcast for topicID: " + topicID + "---defaultNumber=" + defaultNumber + "---defaultContent=" + defaultContent);

        if (defaultNumber == 0 && defaultContent == null) {//OK DONE
            for (int i = 0; i < menu.length; i++) {
                if (menu[i].getType().startsWith("ZZ")) {
                    sizeM += 1;
                    menuHex += menu[i].getType();
                    menuHex += IntegerToHex(menu[i].getContent().length());
                } else {
                    sizeM += 4;
                    menuHex += menu[i].getType() + "81";
                    menuHex += toShortCodeString(menu[i].getShortcode());

                    String tmp = IntegerToHex(menu[i].getContent().length());
                    if (menu[i].getType().equals("B3")) {
                        tmp = tmp.replaceFirst("0", "8");
                    }

                    menuHex += tmp;
                }

                menuHex += stringToHex(menu[i].getContent());
                menuHex += IntegerToHex(menu[i].getDisplay().length()) + stringToHex(menu[i].getDisplay());

                sizeM += menu[i].getContent().length() + 1;
                sizeM += menu[i].getDisplay().length() + 1;
            }

            lengthHide = 12 + sizeM;

            sizeD = detail.length();

            for (int i = 1; i <= 5; i++) {
                int tmp = 21 + sizeD + 6 + sizeM - 8 + 9 * i;
                LOG.debug("Test bug: " + tmp + "--" + i * SIZE_1_PART);
                if (tmp <= i * SIZE_1_PART) {
                    n = i;
                    realSize = tmp;
                    sum = new byte[i * SIZE_1_PART];
                    break;
                }
            }

            // Init
            beginHex = IntegerToHex(serialNumber) + "1066F211" + IntegerToHex(messageID) + "" + 1 + "" + n + IntegerToHex(lengthHide) + "30"
                    + IntegerToHex(numberMenu + 1) + IntegerToHex(topicID)
                    + "0000F00511030101" + IntegerToHex(topicID);

            detailHex = "010200" + IntegerToHex(sizeD + 2) + "3E3E" + stringToHex(detail);

            int k = n * SIZE_1_PART - realSize;
            for (int i = 0; i < k; i++) {
                detailHex += "0D";
            }
        } else if (defaultNumber != 0 && defaultContent == null) {//OK DONE
            for (int i = 0; i < menu.length; i++) {
                if (menu[i].getType().equals("A3")) {
                    if (menu[i].getShortcode() == defaultNumber) {
                        menu[i].setType("A0");
                        sizeM += 1;
                        menuHex += menu[i].getType();
                    } else {
                        sizeM += 4;
                        menuHex += menu[i].getType() + "81";
                        menuHex += toShortCodeString(menu[i].getShortcode());
                    }
                    menuHex += IntegerToHex(menu[i].getContent().length());

                } else {
                    if (menu[i].getShortcode() == defaultNumber) {
                        menu[i].setType("B0");
                        sizeM += 1;
                        menuHex += menu[i].getType();
                    } else {
                        sizeM += 4;
                        menuHex += menu[i].getType() + "81";
                        menuHex += toShortCodeString(menu[i].getShortcode());
                    }

                    String tmp = IntegerToHex(menu[i].getContent().length());
                    if (menu[i].getType().equals("B3")) {
                        tmp = tmp.replaceFirst("0", "8");
                    }
                    menuHex += tmp;
                }

                menuHex += stringToHex(menu[i].getContent());
                menuHex += IntegerToHex(menu[i].getDisplay().length()) + stringToHex(menu[i].getDisplay());

                sizeM += menu[i].getContent().length() + 1;
                sizeM += menu[i].getDisplay().length() + 1;
            }

            lengthHide = 15 + sizeM;

            sizeD = detail.length();

            for (int i = 1; i <= 5; i++) {
                int tmp = 24 + sizeD + 6 + sizeM - 8 + 9 * i;
                if (tmp <= i * SIZE_1_PART) {
                    n = i;
                    realSize = tmp;
                    sum = new byte[i * SIZE_1_PART];
                    break;
                }
            }

            // Init
            beginHex = IntegerToHex(serialNumber) + "1066F211" + IntegerToHex(messageID) + "" + 1 + "" + n + IntegerToHex(lengthHide) + "30"
                    + IntegerToHex(numberMenu + 1) + IntegerToHex(topicID)
                    + "0381" + toShortCodeString(defaultNumber) + "00F00511030101" + IntegerToHex(topicID);

            detailHex = "010200" + IntegerToHex(sizeD + 2) + "3E3E" + stringToHex(detail);

            int k = n * SIZE_1_PART - realSize;
            for (int i = 0; i < k; i++) {
                detailHex += "0D";
            }
        } else if (defaultNumber == 0 && defaultContent != null) {
            for (int i = 0; i < menu.length; i++) {
                sizeM += 4;
                menuHex += menu[i].getType() + "81";
                menuHex += toShortCodeString(menu[i].getShortcode());

                if (menu[i].getContent().equals(defaultContent)) {
                    if (menu[i].getType().startsWith("A")) {
                        menuHex += "00";
                    } else {
                        menuHex += "80";
                    }
                    sizeM += 1;
                } else {
                    if (menu[i].getType().startsWith("A")) {
                        menuHex += IntegerToHex(menu[i].getContent().length());
                    } else {
                        String tmp = IntegerToHex(menu[i].getContent().length());
                        if (menu[i].getType().equals("B3")) {
                            tmp = tmp.replaceFirst("0", "8");
                        }
                        menuHex += tmp;
                    }

                    menuHex += stringToHex(menu[i].getContent());
                    sizeM += menu[i].getContent().length() + 1;
                }

                menuHex += IntegerToHex(menu[i].getDisplay().length()) + stringToHex(menu[i].getDisplay());
                sizeM += menu[i].getDisplay().length() + 1;
//				
//
//				menuHex += stringToHex(menu[i].getContent());
//				menuHex += IntegerToHex(menu[i].getDisplay().length()) + stringToHex(menu[i].getDisplay());
//
//				sizeM += menu[i].getContent().length() + 1;
//				sizeM += menu[i].getDisplay().length() + 1;
            }
            //ThanhTT- Them 23-10-2012
            defaultContent = stringToHex(defaultContent);
            //End- ThanhTT

            lengthHide = 12 + defaultContent.length() / 2 + sizeM;

            sizeD = detail.length();

            for (int i = 1; i <= 5; i++) {
                int tmp = 21 + defaultContent.length() / 2 + sizeD + 6 + sizeM - 8 + 9 * i;
                if (tmp <= i * SIZE_1_PART) {
                    n = i;
                    realSize = tmp;
                    sum = new byte[i * SIZE_1_PART];
                    break;
                }
            }

            // Init
            beginHex = IntegerToHex(serialNumber) + "1066F211" + IntegerToHex(messageID) + "" + 1 + "" + n + IntegerToHex(lengthHide) + "30"
                    + IntegerToHex(numberMenu + 1) + IntegerToHex(topicID)
                    + "00" + IntegerToHex(defaultContent.length() / 2) + defaultContent + "F00511030101" + IntegerToHex(topicID);

            detailHex = "010200" + IntegerToHex(sizeD + 2) + "3E3E" + stringToHex(detail);

            int k = n * SIZE_1_PART - realSize;
            for (int i = 0; i < k; i++) {
                detailHex += "0D";
            }
        } else if (defaultNumber != 0 && defaultContent != null) {
            for (int i = 0; i < menu.length; i++) {
                if (menu[i].getType().equals("A3")) {
                    if (menu[i].getShortcode() == defaultNumber) {
                        menu[i].setType("A0");
                        sizeM += 1;
                        menuHex += menu[i].getType();
                    } else {
                        sizeM += 4;
                        menuHex += menu[i].getType() + "81";
                        menuHex += toShortCodeString(menu[i].getShortcode());
                    }
                } else {
                    if (menu[i].getShortcode() == defaultNumber) {
                        menu[i].setType("B0");
                        sizeM += 1;
                        menuHex += menu[i].getType();
                    } else {
                        sizeM += 4;
                        menuHex += menu[i].getType() + "81";
                        menuHex += toShortCodeString(menu[i].getShortcode());
                    }
                }

                if (menu[i].getContent().equals(defaultContent)) {
                    if (menu[i].getType().startsWith("A")) {
                        menuHex += "00";
                    } else {
                        menuHex += "80";
                    }
                    sizeM += 1;
                } else {
                    if (menu[i].getType().startsWith("A")) {
                        menuHex += IntegerToHex(menu[i].getContent().length());
                    } else {
                        String tmp = IntegerToHex(menu[i].getContent().length());
                        if (menu[i].getType().equals("B3")) {
                            tmp = tmp.replaceFirst("0", "8");
                        }
                        menuHex += tmp;
                    }

                    menuHex += stringToHex(menu[i].getContent());
                    sizeM += menu[i].getContent().length() + 1;
                }

                menuHex += IntegerToHex(menu[i].getDisplay().length()) + stringToHex(menu[i].getDisplay());
                sizeM += menu[i].getDisplay().length() + 1;
            }
            //ThanhTT- Them 23-10-2012
            defaultContent = stringToHex(defaultContent);
            //End- ThanhTT

            lengthHide = 15 + defaultContent.length() / 2 + sizeM;

            sizeD = detail.length();

            for (int i = 1; i <= 5; i++) {
                int tmp = 24 + defaultContent.length() / 2 + sizeD + 6 + sizeM - 8 + 9 * i;
                if (tmp <= i * SIZE_1_PART) {
                    n = i;
                    realSize = tmp;
                    sum = new byte[i * SIZE_1_PART];
                    break;
                }
            }

            // Init
            beginHex = IntegerToHex(serialNumber) + "1066F211" + IntegerToHex(messageID) + "" + 1 + "" + n + IntegerToHex(lengthHide) + "30"
                    + IntegerToHex(numberMenu + 1) + IntegerToHex(topicID)
                    + "0381" + toShortCodeString(defaultNumber) + IntegerToHex(defaultContent.length() / 2) + defaultContent + "F00511030101" + IntegerToHex(topicID);

            detailHex = "010200" + IntegerToHex(sizeD + 2) + "3E3E" + stringToHex(detail);

            int k = n * SIZE_1_PART - realSize;
            for (int i = 0; i < k; i++) {
                detailHex += "0D";
            }
        }

        LOG.debug("Test broadcast: " + beginHex + "---" + menuHex + "---" + detailHex);

        byte[] beginArray = hexStringToByteArray(beginHex);
        byte[] menuArray = hexStringToByteArray(menuHex);
        byte[] detailArray = hexStringToByteArray(detailHex);

        sum = new byte[beginArray.length + menuArray.length + detailArray.length];
        System.arraycopy(beginArray, 0, sum, 0, beginArray.length);
        System.arraycopy(menuArray, 0, sum, beginArray.length, menuArray.length);
        System.arraycopy(detailArray, 0, sum, beginArray.length + menuArray.length, detailArray.length);

        int index = 0;
        Random rnd = new Random();
        int newIndex = rnd.nextInt(10000);
        for (int i = 0; i < n; i++) {
            byte[] out = new byte[88];
            if (i > 0) {
                serialNumber = serialNumber + i * 16;
                String start = IntegerToHex(serialNumber) + "1066F211" + IntegerToHex(messageID) + "" + (i + 1) + "" + n;
                byte[] startArray = hexStringToByteArray(start);

                System.arraycopy(startArray, 0, out, 0, startArray.length);
                System.arraycopy(sum, index, out, 8, 87 - startArray.length);
                index = index + (87 - startArray.length);
            } else {
                System.arraycopy(sum, 0, out, 0, 87);
                index = 87;
            }

            out[87] = (byte) 0xFF;

            byte[] out_file = new byte[82];
            System.arraycopy(out, 6, out_file, 0, 82);

            
            String convertBinary2Hexadecimal = convertBinary2Hexadecimal(out_file);
            
        }
 
        return new ArrayList<String>();
    }
}
